#include "LoginLayer.h"
#include <tcResource/tc_resource.h>
#include <tcNetwork/tc_network.h>
#include "PlayerListLayer.h"

//extern "C" __declspec(dllimport) bool tc_network_login(char *user_name, void (*callback)(int status));

#define FONT_NAME	"Arial"
#define FONT_SIZE	22

LoginLayer::LoginLayer(void) {}
LoginLayer::~LoginLayer(void) {}

CCRect getRect(CCNode * pNode)
{
    CCRect rc;
    rc.origin = pNode->getPosition();
    rc.size = pNode->getContentSize();
    rc.origin.x -= rc.size.width / 2;
    rc.origin.y -= rc.size.height / 2;
    return rc;
}

CCScene* LoginLayer::scene()
{
	CCScene *scene = CCScene::node();
	CCSize screenSize = CCDirector::sharedDirector()->getWinSize();

	{
		CCLayer *backgroundLayer = CCLayer::node();
		char path[128];
		tc_resource_get_path(TC_IMG_BG, path);
		CCSprite *background = CCSprite::spriteWithFile(path);
		background->setPosition(ccp(screenSize.width/2, screenSize.height/2));
		backgroundLayer->addChild(background, 1);
		scene->addChild(backgroundLayer);
	}

	{
		LoginLayer *layer = LoginLayer::node();
		scene->addChild(layer);
	}

	return scene;	
}

bool LoginLayer::init()
{
	CCLayer::init();
	this->setIsTouchEnabled(true);

	//scheduleUpdate();
	return true;
}

void LoginLayer::onEnter() {
	CCLayer::onEnter();
	CCSize screenSize = CCDirector::sharedDirector()->getWinSize();
	char path[128];
	tc_resource_get_path(TC_IMG_LOGIN_IMAGE, path);
	CCSprite *login_image = CCSprite::spriteWithFile(path);
	login_image->setPosition(ccp(screenSize.width/2, screenSize.height/2));
	this->addChild(login_image, 1);

	// menu
	tc_resource_get_path(TC_IMG_LOGIN_BUTTON, path);
    CCMenuItemImage *login_button = CCMenuItemImage::itemFromNormalImage(path, path, this, menu_selector(LoginLayer::loginCallBack) );
    tc_resource_get_path(TC_IMG_EXIT_BUTTON, path);
	CCMenuItemImage *exit_button = CCMenuItemImage::itemFromNormalImage(path, path, this, menu_selector(LoginLayer::exitCallBack) );
 
    CCMenu *menu = CCMenu::menuWithItems(login_button, exit_button, NULL);

    menu->setPosition(CCPointZero);
    login_button->setPosition(CCPointMake( screenSize.width/2 - 57, 136));
    exit_button->setPosition(CCPointMake( screenSize.width/2 + 57, 136));

    addChild(menu, 1);	

	addTextInputLayer();
}

void LoginLayer::addTextInputLayer()
{
    TextFieldTTFActionTest* pTestLayer = new TextFieldTTFActionTest();
    pTestLayer->autorelease();
    this->addKeyboardNotificationLayer(pTestLayer);
}

void LoginLayer::addKeyboardNotificationLayer(TextFieldTTFActionTest *pLayer)
{
    m_pNotificationLayer = pLayer;
    addChild(pLayer, 2);
}

void LoginLayer::exitCallBack(CCObject* pSender) {
	CCDirector::sharedDirector()->end();

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
	exit(0);
#endif
}

void login_callback(int status) {
	if(status == LOGIN_SUCCEED) {
		CCScene* pScene = CCTransitionCrossFade::transitionWithDuration(0.5f, PlayerListLayer::scene());
		if(pScene) {
			CCDirector::sharedDirector()->replaceScene(pScene);
		}
	}
	else if(status == LOGIN_FAILED) {
		CCMessageBox("Login Failed Due To Server Error", "Tan Chess Hint");
	}
}

void LoginLayer::loginCallBack(CCObject* pSender) {
	const char *user_name = m_pNotificationLayer->getText();
	if(tc_network_login(const_cast<char *>(user_name), login_callback) == LOGIN_FAILED) {
		CCMessageBox("Login Failed Due To Network Config Error", "Tan Chess Hint");
	}
	//Sleep(1000);
	//tc_network_get_online_players(NULL);
}

//////////////////////////////////////////////////////////////////////////
// implement KeyboardNotificationLayer
//////////////////////////////////////////////////////////////////////////

KeyboardNotificationLayer::KeyboardNotificationLayer()
: m_pTrackNode(0)
{
    setIsTouchEnabled(true);
}

void KeyboardNotificationLayer::registerWithTouchDispatcher()
{
    CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this, 0, false);
}

void KeyboardNotificationLayer::keyboardWillShow(CCIMEKeyboardNotificationInfo& info)
{
    CCLOG("TextInputTest:keyboardWillShowAt(origin:%f,%f, size:%f,%f)",
        info.end.origin.x, info.end.origin.y, info.end.size.width, info.end.size.height);

    if (! m_pTrackNode)
    {
        return;
    }

    CCRect rectTracked = getRect(m_pTrackNode);
    CCLOG("TextInputTest:trackingNodeAt(origin:%f,%f, size:%f,%f)",
        rectTracked.origin.x, rectTracked.origin.y, rectTracked.size.width, rectTracked.size.height);

    // if the keyboard area doesn't intersect with the tracking node area, nothing need to do.
    if (! CCRect::CCRectIntersectsRect(rectTracked, info.end))
    {
        return;
    }

    // assume keyboard at the bottom of screen, calculate the vertical adjustment.
    float adjustVert = CCRect::CCRectGetMaxY(info.end) - CCRect::CCRectGetMinY(rectTracked);
    CCLOG("TextInputTest:needAdjustVerticalPosition(%f)", adjustVert);

    // move all the children node of KeyboardNotificationLayer
    CCArray * children = getChildren();
    CCNode * node = 0;
    int count = children->count();
    CCPoint pos;
    for (int i = 0; i < count; ++i)
    {
        node = (CCNode*)children->objectAtIndex(i);
        pos = node->getPosition();
        pos.y += adjustVert;
        node->setPosition(pos);
    }
}

// CCLayer function

bool KeyboardNotificationLayer::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
    CCLOG("++++++++++++++++++++++++++++++++++++++++++++");
    m_beginPos = pTouch->locationInView(pTouch->view());	
    m_beginPos = CCDirector::sharedDirector()->convertToGL(m_beginPos);
    return true;
}

void KeyboardNotificationLayer::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
{
    if (! m_pTrackNode)
    {
        return;
    }
    
    CCPoint endPos = pTouch->locationInView(pTouch->view());	
    endPos = CCDirector::sharedDirector()->convertToGL(endPos);

    float delta = 5.0f;
    if (::abs(endPos.x - m_beginPos.x) > delta
        || ::abs(endPos.y - m_beginPos.y) > delta)
    {
        // not click
        m_beginPos.x = m_beginPos.y = -1;
        return;
    }

    // decide the trackNode is clicked.
    CCRect rect;
    CCPoint point = convertTouchToNodeSpaceAR(pTouch);
    CCLOG("KeyboardNotificationLayer:clickedAt(%f,%f)", point.x, point.y);

    rect = getRect(m_pTrackNode);
    CCLOG("KeyboardNotificationLayer:TrackNode at(origin:%f,%f, size:%f,%f)",
        rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);

    this->onClickTrackNode(CCRect::CCRectContainsPoint(rect, point));
    CCLOG("----------------------------------");
}

//////////////////////////////////////////////////////////////////////////
// implement TextFieldTTFActionTest
//////////////////////////////////////////////////////////////////////////

std::string TextFieldTTFActionTest::subtitle()
{
    return "CCTextFieldTTF with action and char limit test";
}

void TextFieldTTFActionTest::onClickTrackNode(bool bClicked)
{
    CCTextFieldTTF * pTextField = (CCTextFieldTTF*)m_pTrackNode;
    if (bClicked)
    {
        // TextFieldTTFTest be clicked
        CCLOG("TextFieldTTFActionTest:CCTextFieldTTF attachWithIME");
        pTextField->attachWithIME();
    }
    else
    {
        // TextFieldTTFTest not be clicked
        CCLOG("TextFieldTTFActionTest:CCTextFieldTTF detachWithIME");
        pTextField->detachWithIME();
    }
}

void TextFieldTTFActionTest::onEnter()
{
    KeyboardNotificationLayer::onEnter();

    m_nCharLimit = 10;

    m_pTextFieldAction = CCRepeatForever::actionWithAction(
        (CCActionInterval*)CCSequence::actions(
            CCFadeOut::actionWithDuration(0.25),
            CCFadeIn::actionWithDuration(0.25),
            0
        ));
    m_pTextFieldAction->retain();
    m_bAction = false;

    // add CCTextFieldTTF
    CCSize s = CCDirector::sharedDirector()->getWinSize();

    m_pTextField = CCTextFieldTTF::textFieldWithPlaceHolder("enter name",
        FONT_NAME,
        FONT_SIZE);
    addChild(m_pTextField);
	ccColor3B color = {0, 0, 0};
    m_pTextField->setColor(color);

    m_pTextField->setDelegate(this);
	
	m_pTextField->setPosition(ccp(193, s.height - 294));

    m_pTrackNode = m_pTextField;
}

void TextFieldTTFActionTest::onExit()
{
    KeyboardNotificationLayer::onExit();
    m_pTextFieldAction->release();
}

// CCTextFieldDelegate protocol
bool TextFieldTTFActionTest::onTextFieldAttachWithIME(CCTextFieldTTF * pSender)
{
    if (! m_bAction)
    {
        m_pTextField->runAction(m_pTextFieldAction);
        m_bAction = true;
    }
    return false;
}

bool TextFieldTTFActionTest::onTextFieldDetachWithIME(CCTextFieldTTF * pSender)
{
    if (m_bAction)
    {
        m_pTextField->stopAction(m_pTextFieldAction);
        m_pTextField->setOpacity(255);
        m_bAction = false;
    }
    return false;
}

bool TextFieldTTFActionTest::onTextFieldInsertText(CCTextFieldTTF * pSender, const char * text, int nLen)
{
    // if insert enter, treat as default to detach with ime
    if ('\n' == *text)
    {
        return false;
    }
    
    // if the textfield's char count more than m_nCharLimit, doesn't insert text anymore.
    if (pSender->getCharCount() >= m_nCharLimit)
    {
        return true;
    }

    // create a insert text sprite and do some action
    CCLabelTTF * label = CCLabelTTF::labelWithString(text, FONT_NAME, FONT_SIZE);
    this->addChild(label);
    ccColor3B color = {0, 0, 0};
    label->setColor(color);

    // move the sprite from top to position
    CCPoint endPos = pSender->getPosition();
    if (pSender->getCharCount())
    {
        endPos.x += pSender->getContentSize().width / 2;
    }
    CCSize  inputTextSize = label->getContentSize();
    CCPoint beginPos(endPos.x, CCDirector::sharedDirector()->getWinSize().height - inputTextSize.height * 2); 

    ccTime duration = 0.5;
    label->setPosition(beginPos);
    label->setScale(8);

    CCAction * seq = CCSequence::actions(
        CCSpawn::actions(
            CCMoveTo::actionWithDuration(duration, endPos),
            CCScaleTo::actionWithDuration(duration, 1),
            CCFadeOut::actionWithDuration(duration),
        0),
        CCCallFuncN::actionWithTarget(this, callfuncN_selector(TextFieldTTFActionTest::callbackRemoveNodeWhenDidAction)),
        0);
    label->runAction(seq);
    return false;
}

bool TextFieldTTFActionTest::onTextFieldDeleteBackward(CCTextFieldTTF * pSender, const char * delText, int nLen)
{
    // create a delete text sprite and do some action
    CCLabelTTF * label = CCLabelTTF::labelWithString(delText, FONT_NAME, FONT_SIZE);
    this->addChild(label);
	ccColor3B color = {0, 0, 0};
    label->setColor(color);

    // move the sprite to fly out
    CCPoint beginPos = pSender->getPosition();
    CCSize textfieldSize = pSender->getContentSize();
    CCSize labelSize = label->getContentSize();
    beginPos.x += (textfieldSize.width - labelSize.width) / 2.0f;
    
    CCSize winSize = CCDirector::sharedDirector()->getWinSize();
    CCPoint endPos(- winSize.width / 4.0f, winSize.height * (0.5 + (float)rand() / (2.0f * RAND_MAX)));

    ccTime duration = 1;
    ccTime rotateDuration = 0.2f;
    int repeatTime = 5; 
    label->setPosition(beginPos);

    CCAction * seq = CCSequence::actions(
        CCSpawn::actions(
            CCMoveTo::actionWithDuration(duration, endPos),
            CCRepeat::actionWithAction(
                CCRotateBy::actionWithDuration(rotateDuration, (rand()%2) ? 360 : -360),
                repeatTime),
            CCFadeOut::actionWithDuration(duration),
        0),
        CCCallFuncN::actionWithTarget(this, callfuncN_selector(TextFieldTTFActionTest::callbackRemoveNodeWhenDidAction)),
        0);
    label->runAction(seq);
    return false;
}

bool TextFieldTTFActionTest::onDraw(CCTextFieldTTF * pSender)
{
    return false;
}

void TextFieldTTFActionTest::callbackRemoveNodeWhenDidAction(CCNode * pNode)
{
    this->removeChild(pNode, true);
}
